home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1993 July / InfoMagic USENET CD-ROM July 1993.ISO / sources / unix / volume22 / multitee2.0 < prev    next >
Encoding:
Internet Message Format  |  1990-06-07  |  22.9 KB

  1. Subject:  v22i006:  Send multiple inputs to multiple outputs
  2. Newsgroups: comp.sources.unix
  3. Approved: rsalz@uunet.UU.NET
  4. X-Checksum-Snefru: 20a304ad ccfd1bd0 63a78fe0 7093dc95
  5.  
  6. Submitted-by: Dan Bernstein <brnstnd@stealth.acf.nyu.edu>
  7. Posting-number: Volume 22, Issue 6
  8. Archive-name: multitee2.0
  9.  
  10. [  The following one-line summary is really all you need, any other
  11.    attempt I made to abstract the manpage ended up with the whole
  12.    thing. :-)  --r$  ]
  13.  
  14. multitee - send multiple inputs to multiple outputs
  15.  
  16. This program is designed for BSD 4.3 variants. Earlier systems don't
  17. provide true per-process non-blocking output.
  18.  
  19. Files:
  20. CHANGES         Description of changes since first distributed version
  21. README          This document
  22. Makefile        Installation commands
  23. multitee.c      The program
  24. multitee.man    Documentation
  25.  
  26. Edit the options in Makefile and type make. multitee will be the
  27. executable program; multitee.1 will be the nroff'ed documentation.
  28.  
  29. I don't pretend to know your machine's setup so there's no make install.
  30.  
  31. Read CHANGES for a list of changes. Type multitee -C and multitee -W
  32. for copyright and warranty information, multitee -H for help.
  33. ---Dan
  34.  
  35. #! /bin/sh
  36. # This is a shell archive.  Remove anything before this line, then unpack
  37. # it by saving it into a file and typing "sh file".  To overwrite existing
  38. # files, type "sh file -c".  You can also feed this as standard input via
  39. # unshar, or by typing "sh <file", e.g..  If this archive is complete, you
  40. # will see the following message at the end:
  41. #        "End of shell archive."
  42. # Contents:  CHANGES README Makefile multitee.man multitee.c djberr.h
  43. # Wrapped by brnstnd@stealth on Tue Mar 27 11:18:08 1990
  44. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  45. if test -f 'CHANGES' -a "${1}" != "-c" ; then 
  46.   echo shar: Will not clobber existing file \"'CHANGES'\"
  47. else
  48. echo shar: Extracting \"'CHANGES'\" \(190 characters\)
  49. sed "s/^X//" >'CHANGES' <<'END_OF_FILE'
  50. X3/27/90: multitee version 2.0
  51. X
  52. XBuffer limits so multitee won't take over the machine.
  53. X
  54. XDies correctly.
  55. XLots of minor improvements.
  56. XAll error cases dealt with.
  57. X
  58. X2/21/90: multitee version 1.0
  59. END_OF_FILE
  60. if test 190 -ne `wc -c <'CHANGES'`; then
  61.     echo shar: \"'CHANGES'\" unpacked with wrong size!
  62. fi
  63. # end of 'CHANGES'
  64. fi
  65. if test -f 'README' -a "${1}" != "-c" ; then 
  66.   echo shar: Will not clobber existing file \"'README'\"
  67. else
  68. echo shar: Extracting \"'README'\" \(857 characters\)
  69. sed "s/^X//" >'README' <<'END_OF_FILE'
  70. Xmultitee - send multiple inputs to multiple outputs
  71. X
  72. XThis program is designed for BSD 4.3 variants. Earlier systems don't
  73. Xprovide true per-process non-blocking output.
  74. X
  75. Xmultitee version 2.0, March 27, 1990.
  76. XCopyright (c) 1990, Daniel J. Bernstein.
  77. XAll rights reserved.
  78. X
  79. XThis distribution packaged March 27, 1990.
  80. X
  81. XFiles:
  82. XCHANGES         Description of changes since first distributed version
  83. XREADME          This document
  84. XMakefile        Installation commands
  85. Xmultitee.c      The program
  86. Xmultitee.man    Documentation
  87. X
  88. XEdit the options in Makefile and type make. multitee will be the
  89. Xexecutable program; multitee.1 will be the nroff'ed documentation.
  90. X
  91. XI don't pretend to know your machine's setup so there's no make install.
  92. X
  93. XRead CHANGES for a list of changes. Type multitee -C and multitee -W
  94. Xfor copyright and warranty information, multitee -H for help.
  95. END_OF_FILE
  96. if test 857 -ne `wc -c <'README'`; then
  97.     echo shar: \"'README'\" unpacked with wrong size!
  98. fi
  99. # end of 'README'
  100. fi
  101. if test -f 'Makefile' -a "${1}" != "-c" ; then 
  102.   echo shar: Will not clobber existing file \"'Makefile'\"
  103. else
  104. echo shar: Extracting \"'Makefile'\" \(822 characters\)
  105. sed "s/^X//" >'Makefile' <<'END_OF_FILE'
  106. XCC=cc
  107. XCCOPTS=-O -UNOSIGINTERRUPT
  108. XNROFFOPTS=-man
  109. X
  110. X# -DNOSIGINTERRUPT if your machine does not have siginterrupt():
  111. X#                  such machines do not support per-process non-blocking I/O
  112. X# -DFDTABLESIZE=nn to override default of FD_SETSIZE
  113. X# -DBUFINSIZE=nnnn to override default of 4096
  114. X# -DMAXBUFOUTSIZE=nnnn to override the default default of 16384
  115. X
  116. Xdefault: all
  117. X
  118. Xall: multitee multitee.1
  119. X
  120. Xshar: multitee.shar
  121. X
  122. Xmultitee: multitee.o Makefile
  123. X    $(CC) $(CCOPTS) -o multitee multitee.o
  124. X
  125. Xmultitee.o: multitee.c Makefile
  126. X    $(CC) $(CCOPTS) -c multitee.o multitee.c
  127. X
  128. Xmultitee.1: multitee.man Makefile
  129. X    nroff $(NROFFOPTS) < multitee.man > multitee.1
  130. X
  131. Xmultitee.shar: CHANGES README Makefile multitee.man multitee.c djberr.h
  132. X    shar CHANGES README Makefile multitee.man multitee.c djberr.h > multitee.shar
  133. X    chmod 400 multitee.shar
  134. END_OF_FILE
  135. if test 822 -ne `wc -c <'Makefile'`; then
  136.     echo shar: \"'Makefile'\" unpacked with wrong size!
  137. fi
  138. # end of 'Makefile'
  139. fi
  140. if test -f 'multitee.man' -a "${1}" != "-c" ; then 
  141.   echo shar: Will not clobber existing file \"'multitee.man'\"
  142. else
  143. echo shar: Extracting \"'multitee.man'\" \(3286 characters\)
  144. sed "s/^X//" >'multitee.man' <<'END_OF_FILE'
  145. X.TH multitee 1
  146. X.SH NAME
  147. Xmultitee \- send multiple inputs to multiple outputs
  148. X.SH SYNTAX
  149. Xmultitee
  150. X[
  151. X\fB\-o\fIsz
  152. X] [
  153. X\fB\-bBv\fI
  154. X] [
  155. X\fB\-ACHUVW\fI
  156. X] [
  157. X\fIfd-fd,fd,fd...
  158. X] ...
  159. X.SH DESCRIPTION
  160. X.I multitee
  161. Xsends multiple inputs to multiple outputs.
  162. XGiven an argument of the form
  163. X.I fdin-fdout,fdout,fdout...
  164. Xit will send all input on file descriptor
  165. X.I fdin
  166. Xto each descriptor
  167. X.I fdout.
  168. X.I multitee
  169. Xwill never block reading or writing a descriptor
  170. X(unless it runs out of buffer space---see below).
  171. X.PP
  172. XIn the
  173. X.I fd
  174. Xarguments, hyphens can be replaced with colons,
  175. Xand any 0 can be omitted. Other than that, each
  176. X.I fd
  177. Xmust be an integer in the right range.
  178. XFuture extensions to
  179. X.I multitee
  180. Xmay abuse the syntax of these arguments,
  181. Xso don't insert any extra characters.
  182. X.PP
  183. XOptions
  184. X.B ACHUVW
  185. Xprint the authorship notice,
  186. Xcopyright notice,
  187. Xhelp notice,
  188. Xshort usage summary,
  189. Xversion number,
  190. Xand warranty information respectively.
  191. X.PP
  192. X.I multitee
  193. Xhas several flags:
  194. X.TP 12
  195. X\fB\-o\fIsz
  196. XSet maximum output buffer size to
  197. X.I sz,
  198. Xdefault 16384.
  199. XIf
  200. X.I multitee
  201. Xoverflows an output buffer,
  202. Xit will not read any more characters until the buffer
  203. Xempties down to the maximum buffer size.
  204. XThe actual maximum space taken by buffers is
  205. X.I sz
  206. Xfor each output buffer, plus 4096 per
  207. Xoutput
  208. X.I fd,
  209. Xthough it would take a lot of effort to
  210. Xachieve the latter.
  211. X.TP
  212. X\fB\-b
  213. XNever block, unless out of buffer space.
  214. XThis is the default.
  215. XFor example, if one output stream is blocked,
  216. X.I multitee
  217. Xwill not sit around waiting for it to clear up before it
  218. Xprocesses characters waiting on other streams. This helps
  219. Xprevent deadlock.
  220. X.TP
  221. X\fB\-B
  222. XDon't be so paranoid about blocking.
  223. XSome systems do not support true per-process non-blocking I/O;
  224. Xon such systems,
  225. X.I multitee
  226. Xwill refuse to run unless you specify
  227. X.B\-B.
  228. XUnder
  229. X.B\-B,
  230. X.I multitee
  231. Xmight block when, for instance,
  232. Xit writes more bytes onto a pipe than the pipe has free.
  233. X.PP
  234. X.SH "EXIT VALUE"
  235. X0 if all inputs reach end-of-file normally.
  236. X1 for usage messages.
  237. X2 if a file descriptor is closed.
  238. X3 if
  239. X.I multitee
  240. Xruns out of memory.
  241. X4 in various impossible situations.
  242. X5 if you don't specify
  243. X.B\-B
  244. Xon machines that don't support true per-process non-blocking I/O.
  245. X6 on an I/O error.
  246. X7 on an unrecognized error.
  247. X8 if
  248. X.I multitee
  249. Xhits a secondary storage resource limit
  250. X(past quota, no more disk space, past process file limit).
  251. X.SH DIAGNOSTICS
  252. X.TP
  253. X.I fatal: no memory
  254. X.I multitee
  255. Xhas run out of memory.
  256. X.TP
  257. X.I fatal: out of space
  258. X.I multitee
  259. Xhas exhausted a secondary storage resource,
  260. Xsuch as disk space, disk quota, or maximum file size.
  261. X.TP
  262. X.I fatal: nonblocking I/O not supported
  263. XSelf-explanatory.
  264. X.TP
  265. X.I fatal: unopened fd
  266. XOne of the file descriptors is not open.
  267. XSorry, there's no way to figure out which one.
  268. X.TP
  269. X.I fatal: I/O error
  270. X.I multitee
  271. Xhas encountered an error in disk input or output.
  272. X.TP
  273. X.I weird
  274. XThis includes various errors, none of which can possibly happen.
  275. X.SH RESTRICTIONS
  276. X.I multitee
  277. Xsimply can't work on machines without
  278. X.I siginterrupt(3)
  279. Xas well as it can on machines with that call.
  280. X.SH BUGS
  281. XNone known.
  282. X.SH MACHINES
  283. X.I multitee
  284. Xhas been tested
  285. Xon an Astronautics ZS-2 running ZSUnix
  286. Xand a Sun 4 running SunOS.
  287. X.SH VERSION
  288. Xmultitee version 2.0, dated March 27, 1990.
  289. X.SH AUTHOR
  290. XCopyright 1990, Daniel J. Bernstein.
  291. X.SH "SEE ALSO"
  292. Xtee(1)
  293. END_OF_FILE
  294. if test 3286 -ne `wc -c <'multitee.man'`; then
  295.     echo shar: \"'multitee.man'\" unpacked with wrong size!
  296. fi
  297. # end of 'multitee.man'
  298. fi
  299. if test -f 'multitee.c' -a "${1}" != "-c" ; then 
  300.   echo shar: Will not clobber existing file \"'multitee.c'\"
  301. else
  302. echo shar: Extracting \"'multitee.c'\" \(13252 characters\)
  303. sed "s/^X//" >'multitee.c' <<'END_OF_FILE'
  304. X/*
  305. Xmultitee.c: send multiple inputs to multiple outputs
  306. X*/
  307. X
  308. Xstatic char multiteeauthor[] =
  309. X"multitee was written by Daniel J. Bernstein.\n\
  310. XInternet address: brnstnd@acf10.nyu.edu.\n";
  311. X
  312. Xstatic char multiteeversion[] = 
  313. X"multitee version 2.0, March 27, 1990.\n\
  314. XCopyright (c) 1990, Daniel J. Bernstein.\n\
  315. XAll rights reserved.\n";
  316. X
  317. Xstatic char multiteecopyright[] =
  318. X"multitee version 2.0, March 27, 1990.\n\
  319. XCopyright (c) 1990, Daniel J. Bernstein.\n\
  320. XAll rights reserved.\n\
  321. X\n\
  322. XUntil January 1, 2095, you are granted the following rights: A. To make\n\
  323. Xcopies of this work in original form, so long as (1) the copies are exact\n\
  324. Xand complete; (2) the copies include the copyright notice, this paragraph,\n\
  325. Xand the disclaimer of warranty in their entirety. B. To distribute this\n\
  326. Xwork, or copies made under the provisions above, so long as (1) this is\n\
  327. Xthe original work and not a derivative form; (2) you do not charge a fee\n\
  328. Xfor copying or for distribution; (3) you ensure that the distributed form\n\
  329. Xincludes the copyright notice, this paragraph, and the disclaimer of\n\
  330. Xwarranty in their entirety. These rights are temporary and revocable upon\n\
  331. Xwritten, oral, or other notice by Daniel J. Bernstein. These rights are\n\
  332. Xautomatically revoked on January 1, 2095. This copyright notice shall be\n\
  333. Xgoverned by the laws of the state of New York.\n\
  334. X\n\
  335. XIf you have questions about multitee or about this copyright notice,\n\
  336. Xor if you would like additional rights beyond those granted above,\n\
  337. Xplease feel free to contact the author at brnstnd@acf10.nyu.edu\n\
  338. Xon the Internet.\n";
  339. X
  340. Xstatic char multiteewarranty[] =
  341. X"To the extent permitted by applicable law, Daniel J. Bernstein disclaims\n\
  342. Xall warranties, explicit or implied, including but not limited to the\n\
  343. Ximplied warranties of merchantability and fitness for a particular purpose.\n\
  344. XDaniel J. Bernstein is not and shall not be liable for any damages,\n\
  345. Xincidental or consequential, arising from the use of this program, even\n\
  346. Xif you inform him of the possibility of such damages. This disclaimer\n\
  347. Xshall be governed by the laws of the state of New York.\n\
  348. X\n\
  349. XIn other words, use this program at your own risk.\n\
  350. X\n\
  351. XIf you have questions about multitee or about this disclaimer of warranty,\n\
  352. Xplease feel free to contact the author at brnstnd@acf10.nyu.edu\n\
  353. Xon the Internet.\n";
  354. X
  355. Xstatic char multiteeusage[] =
  356. X"Usage: multitee [ -osz ] [ -bBvACHUVW ] [ fd-fd,fd,fd... ] ... \n\
  357. XHelp:  multitee -H\n";
  358. X
  359. Xstatic char multiteehelp[] =
  360. X"multitee sends multiple inputs to multiple outputs.\n\
  361. X\n\
  362. Xmultitee -A: print authorship notice\n\
  363. Xmultitee -C: print copyright notice\n\
  364. Xmultitee -H: print this notice\n\
  365. Xmultitee -U: print short usage summary\n\
  366. Xmultitee -V: print version number\n\
  367. Xmultitee -W: print disclaimer of warranty\n\
  368. X\n\
  369. Xmultitee [ -osz ] [ -bBv ][ fd-fd,fd,fd... ] ... : read and write descriptors\n\
  370. X  -osz: limit size of each output buffer to sz (default 16384)\n\
  371. X  -b: never block, no matter what (default)\n\
  372. X  -B: don't worry so much about blocking (forced on some systems)\n\
  373. X  -v: print error messages to stderr\n\
  374. X  fdin-fdout,fdout,fdout...: read from fdin, write to each fdout\n\
  375. X                             (0 can be left out, - can be replaced by :)\n\
  376. XExamples: multitee 0:1,2    like normal tee\n\
  377. X      multitee -- -1,2  same thing (-- ends options; -1,2 is 0-1,2)\n\
  378. X          multitee 0-6 6-1  send 0 in to 6 out while sending 6 in to 1 out\n\
  379. X\n\
  380. XIf you have questions about or suggestions for multitee, please feel free\n\
  381. Xto contact the author, Daniel J. Bernstein, at brnstnd@acf10.nyu.edu\n\
  382. Xon the Internet.\n";
  383. X
  384. X#include <stdio.h> /* just for EOF, sigh */
  385. X#include <sys/types.h>
  386. X#include <sys/time.h>
  387. X#include <signal.h>
  388. Xextern char *malloc(); /* sigh */
  389. X#include <errno.h>
  390. Xextern int errno;
  391. Xextern int getopt();
  392. Xextern char *optarg; /* these should be in getopt.h! */
  393. Xextern int optind;
  394. X#include "djberr.h"
  395. X
  396. X#define copy(dst,src,num) bcopy(src,dst,num)
  397. X
  398. X#ifndef FDTABLESIZE
  399. X#define FDTABLESIZE FD_SETSIZE /* or NOFILE from param.h? */
  400. X#endif
  401. X
  402. Xstruct fdlist
  403. X {
  404. X  int fd;
  405. X  struct fdlist *next;
  406. X }
  407. X;
  408. X#define FDNULL ((struct fdlist *) 0)
  409. X
  410. X#ifndef BUFINSIZE
  411. X#define BUFINSIZE 4096
  412. X#endif
  413. X
  414. X#ifndef MAXBUFOUTSIZE
  415. X#define MAXBUFOUTSIZE 16384
  416. X#endif
  417. X
  418. X/* The following kludges always work and are better than nothing. */
  419. X#ifndef EINVAL
  420. X#define EINVAL 0
  421. X#endif
  422. X#ifndef EBADF
  423. X#define EBADF 0
  424. X#endif
  425. X#ifndef EINTR
  426. X#define EINTR 0
  427. X#endif
  428. X#ifndef EWOULDBLOCK
  429. X#define EWOULDBLOCK 0
  430. X#endif
  431. X#ifndef EFAULT
  432. X#define EFAULT 0
  433. X#endif
  434. X#ifndef EIO
  435. X#define EIO 0
  436. X#endif
  437. X#ifndef EPIPE
  438. X#define EPIPE 0
  439. X#endif
  440. X#ifndef EFBIG
  441. X#define EFBIG 0
  442. X#endif
  443. X#ifndef ENOSPC
  444. X#define ENOSPC 0
  445. X#endif
  446. X#ifndef EDQUOT
  447. X#define EDQUOT 0
  448. X#endif
  449. X
  450. Xvoid nothing()
  451. X{
  452. X}
  453. X
  454. Xmain(argc,argv,envp)
  455. Xint argc;
  456. Xchar *argv[];
  457. Xchar *envp[];
  458. X{
  459. X int opt;
  460. X char *bufin;
  461. X int bufinsize;
  462. X char *oldbuf;
  463. X char *bufout[FDTABLESIZE];
  464. X int bufoutsize[FDTABLESIZE];
  465. X int bufoutpos[FDTABLESIZE];
  466. X fd_set rfds;
  467. X fd_set wfds;
  468. X int numrfds;
  469. X int numwfds;
  470. X int numfds;
  471. X struct fdlist *fds[FDTABLESIZE];
  472. X register struct fdlist *t;
  473. X register int i;
  474. X register int j;
  475. X register int r;
  476. X struct itimerval it;
  477. X int flagneverblock = 1;
  478. X int flagverbose = 0;
  479. X int maxbufoutsize = MAXBUFOUTSIZE;
  480. X int flagpastmax = 0;
  481. X int flagdie = 0;
  482. X while ((opt = getopt(argc,argv,"o:bBvACHUVW")) != EOF)
  483. X   switch(opt)
  484. X    {
  485. X     case 'o': maxbufoutsize = atoi(optarg); break;
  486. X     case 'b': flagneverblock = 1; break;
  487. X     case 'B': flagneverblock = 0; break;
  488. X     case 'v': flagverbose = 1; break;
  489. X     case 'A': (void) err(multiteeauthor); exit(1);
  490. X     case 'C': (void) err(multiteecopyright); exit(1);
  491. X     case 'H': (void) err(multiteehelp); exit(1);
  492. X     case 'U': (void) err(multiteeusage); exit(1);
  493. X     case 'V': (void) err(multiteeversion); exit(1);
  494. X     case 'W': (void) err(multiteewarranty); exit(1);
  495. X     case '?': (void) err(multiteeusage); exit(1);
  496. X    }
  497. X argv += optind, argc -= optind;
  498. X
  499. X numrfds = numwfds = 0;
  500. X while (*argv)
  501. X  {
  502. X   i = 0;
  503. X   while (**argv >= '0' && **argv <= '9')
  504. X     i = 10 * i + *((*argv)++) - '0';
  505. X   if (i < 0 || i >= FDTABLESIZE)
  506. X    { if (flagverbose) err(multiteeusage); exit(1); }
  507. X   if (**argv != '-' && **argv != ':')
  508. X    { if (flagverbose) err(multiteeusage); exit(1); }
  509. X   if (i + 1 > numrfds) numrfds = i + 1;
  510. X   do
  511. X    {
  512. X     (*argv)++;
  513. X     j = 0;
  514. X     while (**argv >= '0' && **argv <= '9')
  515. X       j = 10 * j + *((*argv)++) - '0';
  516. X     if (j < 0 || j >= FDTABLESIZE)
  517. X      { if (flagverbose) err(multiteeusage); exit(1); }
  518. X     if (!(t = (struct fdlist *) malloc(sizeof(struct fdlist))))
  519. X       /* XXXXXX: should have manually allocated avail list */
  520. X      { if (flagverbose) errn("multitee: fatal: no memory"); exit(3); }
  521. X     t->fd = j;
  522. X     t->next = fds[i];
  523. X     fds[i] = t;
  524. X     if (j + 1 > numwfds) numwfds = j + 1;
  525. X    }
  526. X   while(**argv == ',');
  527. X   if (**argv) /* not a comma but not a zero */
  528. X    { if (flagverbose) err(multiteeusage); exit(1); }
  529. X   argv++;
  530. X  }
  531. X
  532. X bufinsize = BUFINSIZE;
  533. X if (!(bufin = malloc((unsigned) bufinsize)))
  534. X  { if (flagverbose) errn("multitee: fatal: no memory"); exit(3); }
  535. X if (numrfds > numwfds)
  536. X   numfds = numrfds;
  537. X else
  538. X   numfds = numwfds;
  539. X if (flagneverblock)
  540. X  {
  541. X#ifdef NOSIGINTERRUPT
  542. X   if (flagverbose) errn("multitee: fatal: nonblocking I/O not supported");
  543. X   exit(5);
  544. X#else
  545. X   (void) siginterrupt(SIGALRM,1);
  546. X   (void) signal(SIGALRM,nothing);
  547. X#endif
  548. X  }
  549. X for (;;)
  550. X  {
  551. X   FD_ZERO(&rfds);
  552. X   if (flagpastmax == 0) /* as long as somebody's past, we'll block */
  553. X     for (i = 0;i < numrfds;i++)
  554. X       if (fds[i] != FDNULL)
  555. X         FD_SET(i,&rfds);
  556. X   r = 0;
  557. X   FD_ZERO(&wfds);
  558. X   for (i = 0;i < numwfds;i++)
  559. X     if (bufoutpos[i])
  560. X      {
  561. X       r++;
  562. X       FD_SET(i,&wfds);
  563. X      }
  564. X   if (flagdie && !r)
  565. X     exit(0); /* aaah, a normal exit */
  566. X   r = select(numfds,&rfds,&wfds,(fd_set *) 0,(struct timeval *) 0);
  567. X   if (r == -1)
  568. X     switch(errno)
  569. X      {
  570. X       case EINTR: 
  571. X#ifndef NOSIGINTERRUPT
  572. X         it.it_value.tv_sec = it.it_interval.tv_sec = 0;
  573. X         it.it_value.tv_usec = it.it_interval.tv_usec = 0;
  574. X         (void) setitimer(ITIMER_REAL,&it,(struct itimerval *) 0);
  575. X#endif
  576. X         break; /* turn ALRM off---usually unnecessary */
  577. X       case EINVAL:
  578. X     break; /* impossible */
  579. X       case EBADF:
  580. X     if (flagverbose) errn("multitee: fatal: unopened fd");
  581. X     exit(2); /* annoying: no way to find the bad fd! */
  582. X       default: 
  583. X     break; /* XXXXXX */
  584. X      }
  585. X   else if (r > 0)
  586. X    {
  587. X     if (flagneverblock)
  588. X      {
  589. X#ifndef NOSIGINTERRUPT
  590. X       it.it_value.tv_sec = it.it_interval.tv_sec = 0;
  591. X       it.it_value.tv_usec = it.it_interval.tv_usec = 10000;
  592. X       (void) setitimer(ITIMER_REAL,&it,(struct itimerval *) 0);
  593. X#endif
  594. X      }
  595. X     for (i = 0;i < numrfds;i++)
  596. X       if (FD_ISSET(i,&rfds))
  597. X    {
  598. X     r = read(i,bufin,bufinsize);
  599. X     if (r == -1)
  600. X       switch(errno)
  601. X        {
  602. X         case EINTR: case EWOULDBLOCK:
  603. X           break; /* why readable, then? */
  604. X             case EBADF:
  605. X           if (flagverbose) errn("multitee: weird: unopened read fd");
  606. X           exit(4); /* impossible: select would know */
  607. X             case EINVAL:
  608. X           if (flagverbose) errn("multitee: weird: negative read fd");
  609. X           exit(4); /* impossible: select would know */
  610. X             case EFAULT:
  611. X           if (flagverbose) errn("multitee: weird: read memory fault");
  612. X           exit(4); /* impossible: bufin is allocated */
  613. X         case EIO:
  614. X           if (flagverbose) errn("multitee: fatal: read I/O error");
  615. X           exit(6); /* XXXXXX: there's almost certainly a better way */
  616. X         default: 
  617. X           if (flagverbose) perrn2("%s","multitee: weird: unknown error");
  618. X           exit(7); /* if we dunno what's happening, too bad */
  619. X        }
  620. X     else if (r == 0) /* EOF */
  621. X      {
  622. X       while (fds[i] != FDNULL)
  623. X        {
  624. X         t = fds[i];
  625. X         fds[i] = t->next;
  626. X         (void) free((char *) t);
  627. X        }
  628. X       /* XXXXXX: should have option for ``die on eof here'' */
  629. X       while (fds[numrfds - 1] == FDNULL)
  630. X         numrfds--;
  631. X       if (numrfds == 0)
  632. X         flagdie = 1;
  633. X      }
  634. X     else
  635. X       for (t = fds[i];t != FDNULL;t = t->next)
  636. X        {
  637. X         if (bufoutpos[t->fd] > maxbufoutsize) /* anti-aack! */
  638. X           flagpastmax--; /* otherwise we'd count this pastmax twice */
  639. X         if (bufoutsize[t->fd] - bufoutpos[t->fd] < r)
  640. X          {
  641. X           bufoutsize[t->fd] = ((bufoutpos[t->fd] + r + 255) / 256) * 256;
  642. X           /* can't use realloc: it doesn't return sensible errors */
  643. X           oldbuf = bufout[t->fd];
  644. X           bufout[t->fd] = malloc((unsigned) bufoutsize[t->fd]);
  645. X           if (bufout[t->fd])
  646. X        {
  647. X         (void) copy(bufout[t->fd],oldbuf,bufoutpos[t->fd]);
  648. X         (void) free(oldbuf);
  649. X        }
  650. X           else
  651. X        { /* damn, out of memory */
  652. X         bufout[t->fd] = oldbuf;
  653. X         /* XXXXXX: shouldn't just die... */
  654. X         if (flagverbose) errn("multitee: fatal: no memory");
  655. X         exit(3);
  656. X        }
  657. X          }
  658. X         (void) copy(bufout[t->fd] + bufoutpos[t->fd],bufin,r);
  659. X         bufoutpos[t->fd] += r;
  660. X         if (bufoutpos[t->fd] > maxbufoutsize) /* aack! */
  661. X           flagpastmax++;
  662. X        }
  663. X    }
  664. X     for (i = 0;i < numwfds;i++)
  665. X       if (FD_ISSET(i,&wfds))
  666. X    {
  667. X     r = write(i,bufout[i],bufoutpos[i]);
  668. X     if (r == -1)
  669. X       switch(errno)
  670. X        {
  671. X         case EINTR: case EWOULDBLOCK:
  672. X           break; /* why writable, then? */
  673. X             case EBADF:
  674. X           if (flagverbose) errn("multitee: weird: unopened write fd");
  675. X           exit(4); /* impossible: select would know */
  676. X             case EINVAL:
  677. X           if (flagverbose) errn("multitee: weird: negative write fd");
  678. X           exit(4); /* impossible: select would know */
  679. X             case EFAULT:
  680. X           if (flagverbose) errn("multitee: weird: write memory fault");
  681. X           exit(4); /* impossible: bufout[i] is allocated */
  682. X         case EPIPE:
  683. X           for (j = 0;j < numrfds;j++)
  684. X        {
  685. X         t = fds[j];
  686. X             /* XXXXXX: should have option ``die on broken pipe here'' */
  687. X         while (t != FDNULL)
  688. X           if (t->fd == i)
  689. X            {
  690. X             free((char *) t);
  691. X             t = fds[j]; /* should use extra variable, not retrace */
  692. X            }
  693. X           else
  694. X             t = t->next;
  695. X         if (fds[j] == FDNULL)
  696. X           {
  697. X            /* basically same as eof on read */
  698. X                while (fds[numrfds - 1] == FDNULL)
  699. X                  numrfds--;
  700. X                if (numrfds == 0)
  701. X                  flagdie = 1;
  702. X           }
  703. X        }
  704. X           break;
  705. X         case EFBIG: case ENOSPC: case EDQUOT:
  706. X           if (flagverbose) errn("multitee: fatal: out of space");
  707. X           exit(8); /* XXXXXX: what to do? this is difficult */
  708. X         case EIO:
  709. X           if (flagverbose) errn("multitee: fatal: write I/O error");
  710. X           exit(6); /* XXXXXX: there's almost certainly a better way */
  711. X         default: 
  712. X           if (flagverbose) perrn2("%s","multitee: weird: unknown error");
  713. X           exit(7); /* if we dunno what's happening, too bad */
  714. X        }
  715. X     else if (r == 0)
  716. X      {
  717. X       ; /* wtf does this mean? */
  718. X      }
  719. X     else
  720. X      {
  721. X       if (bufoutpos[i] > maxbufoutsize) /* anti-aack! */
  722. X         flagpastmax--;
  723. X       bufoutpos[i] -= r;
  724. X       if (bufoutpos[i] > 0) /* worth trading test for a function call */
  725. X         copy(bufout[i],bufout[i] + r,bufoutpos[i]);
  726. X       if (bufoutpos[i] > maxbufoutsize) /* aack! */
  727. X         flagpastmax++;
  728. X      }
  729. X    }
  730. X     if (flagneverblock)
  731. X      {
  732. X#ifndef NOSIGINTERRUPT
  733. X       it.it_value.tv_sec = it.it_interval.tv_sec = 0;
  734. X       it.it_value.tv_usec = it.it_interval.tv_usec = 0;
  735. X       (void) setitimer(ITIMER_REAL,&it,(struct itimerval *) 0);
  736. X#endif
  737. X      }
  738. X    }
  739. X  }
  740. X}
  741. END_OF_FILE
  742. if test 13252 -ne `wc -c <'multitee.c'`; then
  743.     echo shar: \"'multitee.c'\" unpacked with wrong size!
  744. fi
  745. # end of 'multitee.c'
  746. fi
  747. if test -f 'djberr.h' -a "${1}" != "-c" ; then 
  748.   echo shar: Will not clobber existing file \"'djberr.h'\"
  749. else
  750. echo shar: Extracting \"'djberr.h'\" \(491 characters\)
  751. sed "s/^X//" >'djberr.h' <<'END_OF_FILE'
  752. X/* djberr.h, 11/1/89. */
  753. X
  754. X#ifndef __DJBERRH_
  755. X#define __DJBERRH_
  756. X
  757. Xextern int errno;
  758. X
  759. X#define errn(s) (((void) fputs(s,stderr)), putc('\n',stderr))
  760. X#define err(s) (fputs(s,stderr))
  761. X#define errn2(s,t) (((void) fprintf(stderr,s,t)), putc('\n',stderr))
  762. X#define errn3(s,t,u) (((void) fprintf(stderr,s,t,u)), putc('\n',stderr))
  763. X#define perrn2(s,t) { int dummyerrno = errno; (void) fprintf(stderr,s,t); \
  764. X              (void) fputs(": ",stderr); errno = dummyerrno; \
  765. X              (void) perror(""); }
  766. X
  767. X#endif
  768. END_OF_FILE
  769. if test 491 -ne `wc -c <'djberr.h'`; then
  770.     echo shar: \"'djberr.h'\" unpacked with wrong size!
  771. fi
  772. # end of 'djberr.h'
  773. fi
  774. echo shar: End of shell archive.
  775. exit 0
  776.  
  777. exit 0 # Just in case...
  778.